package DCSource.Crypt;

import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class Security {
	private static KeyPairGenerator kpg = null;
	private KeyPair key = null;
	private Cipher crypter = null;
	private Cipher decrypter = null;
	public static KeyPair generatePair(int keysize) throws NoSuchAlgorithmException, NoSuchProviderException{
		if (keysize<512){
			keysize=512;
		}
		if (keysize>16384){
			keysize=16384;
		}
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
		kpg = KeyPairGenerator.getInstance("RSA");
		kpg.initialize(keysize, random);
		return kpg.genKeyPair();
	}
	public static KeyPair createKeyPair(byte[] encodedPrivateKey, byte[] encodedPublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        KeyFactory generator = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = generator.generatePrivate(privateKeySpec);

        EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        PublicKey publicKey = generator.generatePublic(publicKeySpec);
        return new KeyPair(publicKey, privateKey);
	}
	public static PublicKey createPublicKey(byte[] encodedPublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory generator = KeyFactory.getInstance("RSA");
        EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        PublicKey publicKey = generator.generatePublic(publicKeySpec);
        return publicKey;
	}
	public static PrivateKey createPrivateKey(byte[] encodedPrivateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        KeyFactory generator = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = generator.generatePrivate(privateKeySpec);
        return privateKey;
	}
	public static byte[] encrypt(byte[] c,PublicKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
		Cipher tmpcrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		tmpcrypter.init(Cipher.ENCRYPT_MODE,key);
		return tmpcrypter.doFinal(c);
	}
	public static byte[] decrypt(byte[] c,PrivateKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
		Cipher tmpcrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		tmpcrypter.init(Cipher.DECRYPT_MODE,key);
		return tmpcrypter.doFinal(c);
	}
	public static byte[] encrypt(byte[] c,PublicKey key, int csize) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
		Cipher tmpcrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		tmpcrypter.init(Cipher.ENCRYPT_MODE,key);
		return tmpcrypter.doFinal(c,0,csize);
	}
	public static byte[] decrypt(byte[] c,PrivateKey key, int csize) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
		Cipher tmpcrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		tmpcrypter.init(Cipher.DECRYPT_MODE,key);
		return tmpcrypter.doFinal(c,0,csize);
	}
	public static CipherOutputStream converTo(OutputStream b, PublicKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{
		Cipher tmpcrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		tmpcrypter.init(Cipher.ENCRYPT_MODE,key);
		return new CipherOutputStream(b,tmpcrypter);
	}
	public static CipherInputStream converTo(InputStream b, PrivateKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{
		Cipher tmpcrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		tmpcrypter.init(Cipher.DECRYPT_MODE,key);
		return new CipherInputStream(b,tmpcrypter);
	}
	public Security(int keysize){
		try{
			if (keysize<512){
				keysize=512;
			}
			if (keysize>16384){
				keysize=16384;
			}
			SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
			kpg = KeyPairGenerator.getInstance("RSA");
			kpg.initialize(keysize, random);
			key = kpg.genKeyPair();
			crypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
			crypter.init(Cipher.ENCRYPT_MODE, key.getPublic());
			decrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
			decrypter.init(Cipher.DECRYPT_MODE, key.getPrivate());
		}catch(Exception err){
			
		}
	}
	public Security(PublicKey publicKey, PrivateKey privateKey){
		try{
			key = new KeyPair(publicKey,privateKey);
			crypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
			crypter.init(Cipher.ENCRYPT_MODE, key.getPublic());
			decrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
			decrypter.init(Cipher.DECRYPT_MODE, key.getPrivate());
		}catch(Exception err){
			
		}
	}
	public PublicKey getPublic(){
		return key.getPublic();
	}
	public PrivateKey getPrivate(){
		return key.getPrivate();
	}
	public byte[] encrypt(byte[] get) throws IllegalBlockSizeException, BadPaddingException{
		return crypter.doFinal(get);
	}
	public byte[] decrypt(byte[] get) throws IllegalBlockSizeException, BadPaddingException{
		return decrypter.doFinal(get);
	}
	public byte[] encrypt(byte[] get, int csize) throws IllegalBlockSizeException, BadPaddingException{
		return crypter.doFinal(get,0,csize);
	}
	public byte[] decrypt(byte[] get, int csize) throws IllegalBlockSizeException, BadPaddingException{
		return decrypter.doFinal(get,0,csize);
	}
	public void reset() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{
		crypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		crypter.init(Cipher.ENCRYPT_MODE, key.getPublic());
		decrypter = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
		decrypter.init(Cipher.DECRYPT_MODE, key.getPrivate());
	}
	public CipherOutputStream convertTo(OutputStream b){
		return new CipherOutputStream(b,crypter);
	}
	public CipherInputStream converTo(InputStream b){
		return new CipherInputStream(b,decrypter);
	}
}
